package com.aisino.api.util;

import org.apache.commons.text.similarity.LevenshteinDetailedDistance;

import java.util.regex.Pattern;

public class EnterpriseNameSimilarityMatcher {

    // 使用 LevenshteinDetailedDistance 支持子串编辑距离计算
    private static final LevenshteinDetailedDistance DLD = new LevenshteinDetailedDistance();

    // 用于清洗文本中的非中文、非字母数字等噪音字符
    private static final Pattern SPLIT_WORDS = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z0-9]+");

    /**
     * 清洗企业名称：去括号、统一后缀、去行业词、去特殊符号等
     */
    public static String cleanEnterpriseName(String name) {
        if (name == null) return "";
        String cleaned = name.trim();

        // 去掉括号及其中内容（全角/半角）
        cleaned = cleaned.replaceAll("[（(][^）)]*[）)]", "").replaceAll("[()]", "");

        // 统一常见企业后缀，避免干扰
        cleaned = cleaned.replaceAll("股份有限公司", "公司")
                .replaceAll("有限责任公司", "公司")
                .replaceAll("集团有限公司", "集团")
                .replaceAll("责任公司", "公司");

        // 可选：去掉行业噪声词（如医药/制药/药业），如需保留请注释掉
        cleaned = cleaned.replaceAll("医药|制药|药业", "");

        // 去掉多余空格、特殊符号，只保留中文、英文、数字、短横线及括号
        cleaned = cleaned.replaceAll("[\\s　]+", " ") // 全角空格
                .replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9\\-()]+", " ")
                .replaceAll("\\s+", " ")
                .trim();

        return cleaned;
    }

    /**
     * 计算两个字符串的整体相似度 [0.0 ~ 1.0]
     * 相似度 = 1.0 - (编辑距离 / 最大长度)
     */
    public static double sim(String a, String b) {
        if (a.isEmpty() && b.isEmpty()) return 1.0;
        if (a.isEmpty() || b.isEmpty()) return 0.0;
        int d = DLD.apply(a, b).getDistance(); // 使用 DLD 也可以算整体距离，和 LD 一样效果
        int maxLen = Math.max(a.length(), b.length());
        return 1.0 - (double) d / maxLen;
    }

    /**
     * 计算两个字符串的“移位对齐”局部最大相似度
     * 允许局部子串匹配，应对词语顺序不一致的情况
     */
    public static double maxShiftSim(String a, String b, int window) {
        double max = 0.0;

        // 如果任一字符串为空，返回0
        if (a.isEmpty() || b.isEmpty()) {
            return 0.0;
        }

        // 只有当两个字符串都足够长时才进行局部匹配
        if (a.length() < 4 || b.length() < 4) {
            return 0.0;
        }

        // 滑动窗口比较子串
        for (int i = 0; i <= a.length() - 3; i++) {
            for (int j = 0; j <= b.length() - 3; j++) {
                // 限制窗口大小
                if (Math.abs(i - j) > window) continue;

                // 提取至少3个字符的子串进行比较
                int lenA = Math.min(3, a.length() - i);
                int lenB = Math.min(3, b.length() - j);

                if (lenA < 3 || lenB < 3) continue;

                String subA = a.substring(i, i + lenA);
                String subB = b.substring(j, j + lenB);

                int d = DLD.apply(subA, subB).getDistance();
                // 避免除以0的情况
                if (Math.max(subA.length(), subB.length()) == 0) continue;

                double score = 1.0 - (double) d / Math.max(subA.length(), subB.length());

                // 只有当相似度较高时才考虑
                if (score > 0.6 && score > max) {
                    max = score;
                }
            }
        }
        return max;
    }

    /**
     * 综合相似度 = max(整体相似度, 移位对齐局部相似度)
     */
    public static double calculateSimilarity(String name1, String name2) {
        String x1 = cleanEnterpriseName(name1);
        String x2 = cleanEnterpriseName(name2);
        // 只有当清洗后的字符串完全相同时才返回1.0
        if (x1.equals(x2) && !x1.isEmpty()) return 1.0;

        double base = sim(x1, x2);                    // 整体相似度
        double shift = maxShiftSim(x1, x2, 3);        // 局部相似度
        return Math.max(base, shift);
    }

    /**
     * 判断两个企业名称是否可能是同一家（基于相似度阈值）
     */
    public static boolean isLikelySameEnterprise(String name1, String name2, double threshold) {
        return calculateSimilarity(name1, name2) >= threshold;
    }

    // ========== 测试 ==========
    public static void main(String[] args) {
        String[][] testPairs = {
//                {"江西珍视明药业有限公司", "珍视明(江西)药业股份有限公司"},
                {"北京同仁堂股份有限公司", "同仁堂（北京）药业有限公司"},
//                {"江西珍视明药业有限公司", "华润三九医药股份有限公司"},
//                {"杭州海康威视数字技术股份有限公司", "海康威视(杭州)数字技术公司"},
//                {"腾讯科技(深圳)有限公司", "深圳市腾讯科技有限公司"}
        };

        double threshold = 0.75; // 相似度阈值，可调整：0.75 ~ 0.9

        for (String[] pair : testPairs) {
            String name1 = pair[0];
            String name2 = pair[1];

            String cleaned1 = cleanEnterpriseName(name1);
            String cleaned2 = cleanEnterpriseName(name2);

            double similarity = calculateSimilarity(name1, name2);
            boolean likelySame = isLikelySameEnterprise(name1, name2, threshold);

            System.out.printf("【%s】 vs 【%s】\n", name1, name2);
            System.out.printf("  → 清洗后: \"%s\" vs \"%s\"\n", cleaned1, cleaned2);
            System.out.printf("  → 相似度: %.4f\n", similarity);
            System.out.printf("  → 是同一家企业？ %s (阈值=%.2f)\n\n", likelySame, threshold);
        }
    }
}
